package xyz.labradormm.spider.util.forkjoin;

import lombok.extern.slf4j.Slf4j;
import xyz.labradormm.spider.domain.dto.ForkJoinTaskDto;
import xyz.labradormm.spider.util.ByteUtil;
import xyz.labradormm.spider.util.HttpUtils;
import xyz.labradormm.spider.util.RequestWrap;
import xyz.labradormm.spider.util.ResponseWrap;

import java.util.concurrent.RecursiveTask;

/**
 * @author hhj
 * @description
 * @date 2021-09-24 14:36
 * @menu
 */
@Slf4j
public class YtVideoDownloadFJTask extends RecursiveTask<byte[]> {


    /**
     * 字节阈值2MB
     */
    private Long byteThreshold = 2097152L;

    private Long startIndex;

    private Long endIndex;

    private ForkJoinTaskDto forkJoinTaskDto;


    public YtVideoDownloadFJTask(Long startIndex, Long endIndex, ForkJoinTaskDto forkJoinTaskDto) {
        this.forkJoinTaskDto = forkJoinTaskDto;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    @Override
    protected byte[] compute() {
        if ((endIndex - startIndex) <= byteThreshold) {
            byte[] bytes = downloadResource();
            return bytes;
        }
        Long spilit = (endIndex - startIndex) / 2;
        YtVideoDownloadFJTask task1 = new YtVideoDownloadFJTask(startIndex, startIndex + spilit - 1, forkJoinTaskDto);
        YtVideoDownloadFJTask task2 = new YtVideoDownloadFJTask(startIndex + spilit, endIndex, forkJoinTaskDto);
        invokeAll(task1, task2);
        return ByteUtil.byteMerger(task1.join(), task2.join());
    }


    private byte[] downloadResource() {
        try {
            log.info(String.format("开始解析%s—%s段的视频", startIndex, endIndex));
            RequestWrap requestWrap = HttpUtils.getInstance().get(forkJoinTaskDto.getTargetUrl());
            requestWrap.setProxy(forkJoinTaskDto.getVpnProxy());
            requestWrap.setConnectTimeout(5000);
            requestWrap.addHeader("User_Agent", HttpUtils.User_Agent);
            requestWrap.addHeader("Range", "bytes=" + startIndex + "-" + endIndex);
            requestWrap.addHeader("cookie", forkJoinTaskDto.getCookie());
            ResponseWrap responseWrap = requestWrap.execute();
            return responseWrap.getByteArray();
        } catch (Exception e) {
            log.error("YT请求资源异常", e);
            throw e;
        }
    }
}
